﻿namespace Contoso.ActiveDirectory {

    #region Usings
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.DirectoryServices;
    using System.Diagnostics;
    using System.Threading;
    #endregion

    /// <summary>
    /// BitLocker Full Volume Encryption Recovery Information
    /// </summary>
    /// <remarks>
    /// Child object of a computer object
    /// http://windows.microsoft.com/en-us/windows-vista/How-do-I-use-Active-Directory-for-backup-of-BitLocker-Drive-Encryption-recovery-information
    /// Full Volume Encryption (FVE) was the prerelease name for BitLocker Drive Encryption
    /// </remarks>
    [Serializable]
    public class FVERecoveryInfo : ADBaseObjectProperties, IFVERecoveryInfo {

        #region Members

        #region Fields
        public static readonly new string[] AttributesToGet;

        public static readonly string ObjectCategoryShortName = "msfve-RecoveryInformation"; 
        #endregion

        /// <summary>
        /// The distinguished name of the computer that is associated with this FVE object.
        /// </summary>
        public string MSDSParentDistName { get; private set; }

        /// <summary>
        /// A disk volume's BitLocker encryption key secured by the corresponding recovery password. 
        /// </summary>
        public byte[] MSFVEKeyPackage { get; private set; }

        /// <summary>
        /// The GUID associated with a BitLocker recovery password. 
        /// </summary>
        public Guid MSFVERecoveryGuid { get; private set; }

        /// <summary>
        /// A password that can recover a BitLocker-encrypted volume. 
        /// </summary>
        public string MSFVERecoveryPassword { get; private set; }

        /// <summary>
        /// The Guid identifier of the volume
        /// </summary>
        public Guid MSFVEVolumeGuid { get; private set; }

        #endregion

        #region Constructor
        static FVERecoveryInfo() {
            var attributesToGet = new List<string>();

            attributesToGet.AddRange(new string[]
            {
                "msDS-parentdistname",
                "msFVE-KeyPackage",
                "msFVE-RecoveryGuid",
                "msFVE-RecoveryPassword",
                "msFVE-VolumeGuid"
            });

            attributesToGet.AddRange(ADBaseObjectProperties.AttributesToGet);

            AttributesToGet = attributesToGet.Distinct().ToArray();
            attributesToGet = null;
        }
        public FVERecoveryInfo() {            
            this.Initialize();
        }

        public FVERecoveryInfo(DirectoryEntry directoryEntry, bool destroyInputObject = true)
            : base(directoryEntry, destroyInputObject) {
            if (this.GetType().Name == typeof(FVERecoveryInfo).Name) {
                this.Attributes = null;
            }
        }

        public FVERecoveryInfo(SearchResult result, bool destroyInputObject = true)
            : base(result, destroyInputObject) {
            if (this.GetType().Name == typeof(FVERecoveryInfo).Name) {
                this.Attributes = null;
            }
        }
        #endregion

        #region Methods
        protected override void ProcessResults() {

            try {
                base.ProcessResults();

                if (this.Attributes.ContainsKey("msDS-parentdistname")) this.MSDSParentDistName = this.Attributes["msDS-parentdistname"][0].ToString();
                if (this.Attributes.ContainsKey("msFVE-KeyPackage")) this.MSFVEKeyPackage = (byte[])this.Attributes["msFVE-KeyPackage"][0];
                if (this.Attributes.ContainsKey("msFVE-RecoveryGuid")) this.MSFVERecoveryGuid = new Guid((byte[])this.Attributes["msFVE-RecoveryGuid"][0]);
                if (this.Attributes.ContainsKey("msFVE-RecoveryPassword")) this.MSFVERecoveryPassword = this.Attributes["msFVE-RecoveryPassword"][0].ToString();
                if (this.Attributes.ContainsKey("msFVE-VolumeGuid")) this.MSFVEVolumeGuid = new Guid((byte[])this.Attributes["msFVE-VolumeGuid"][0]);

                this.IsValid = !string.IsNullOrWhiteSpace(this.DN)
                    && this.ObjectClass.Any(x => string.Equals(x, ObjectCategoryShortName, StringComparison.OrdinalIgnoreCase));
            }
            catch (Exception e) {
                Debug.WriteLine(string.Format("{0}  [ThreadID: {1}]  {2} Error: {3}", 
                    DateTime.Now.TimeOfDay, Thread.CurrentThread.ManagedThreadId, CustomExtensions.CurrentMethodName(), e.VerboseExceptionString()));
                throw;
            }
        }

        protected override void Initialize() {
            base.Initialize();

            this.MSFVERecoveryPassword = string.Empty;
        }
        #endregion
    }
}
